#ifndef __tenacitas_distributed__server__h__
#define __tenacitas_distributed__server__h__


// =============================================================================
/**
@file 
File description
*/


// =============================================================================
//                                 C++ Headers


// =============================================================================
//                                 3rds Headers


// =============================================================================
//                                 Our Headers

#include <tenacitas_async/handlers.h>
#include <tenacitas_async/event.h>
#include <tenacitas_log/logger.h>

// =============================================================================
//                                 Namespaces
using namespace std;


// =============================================================================
//                                 Macro Contants

/**
*/


// =============================================================================
//                                 Macro Commands

/**
*/


/**
namespace of the organization
*/
namespace tenacitas {
    /**
    namespace for the project
    */
    namespace distributed {

        // =====================================================================
        //                             Typedefs

        /**
        */


        // =====================================================================
        //                             Pre-Declarations


        // =====================================================================
        //                             Attributes

        /**
        */
        static const async::event_id connection_event_id ( 0 );

        // =====================================================================
        //                             Functions

        /**
        */


        // =====================================================================
        //                             Classes

        ///** Type for the connection event

        //@tparam t_connection_ptr is the type of pointer to the connection
        //that will be handled 
        //*/
        //template <typename t_connection>
        //class connection_event :
        //    public async::event1<
        //    connection_event_id,
        //    typename t_connection::ptr_t> { 

        //public:
        //    connection_event( typename t_connection::ptr_t p_conn_ptr )
        //        : async::event1<
        //        connection_event_id,
        //        typename t_connection::ptr_t> ( p_conn_ptr ) {}

        //};


        /**

        @tparam t_supplier must provide:
        <tt>
        typedef logger_t
        typedef connection_t
        typedef handler_t
        typedef handler_creator_t
        typedef receiver_t
        </tt>

        @p handler_t must implement:
        <tt>
        typedef ptr_t;
        
        void operator( )( connection_event<connection_t::ptr_t>::ptr_t )
        </tt>                                       

        @p connection_t must implement
        <tt> typedef ptr_t </tt>

        @p receiver_t must implement
        <tt>connection_event::ptr_t operator( ) ( )</tt>


        @nosubgrouping 
        */
        template <
            typename t_logger, 
            typename t_handler,
            typename t_handler_creator,
            typename t_connection_receiver,
            typename t_connection_event
        >
        class server {

            // -----------------------------------------------------------------
            //    server - Friends

        public:

            // -----------------------------------------------------------------
            //    server - Public Internal Types

            typedef std::shared_ptr<server> ptr_t;

            typedef typename t_logger logger_t;

            typedef typename t_handler_creator handler_creator_t;

            typedef typename handler_creator_t::ptr_t handler_creator_ptr_t;

            typedef typename t_handler handler_t;

            typedef typename t_connection_receiver connection_receiver_t;

            typedef typename connection_receiver_t::ptr_t connection_receiver_ptr_t;

            typedef t_connection_event connection_event_t; 

            typedef typename connection_event_t::ptr_t connection_event_ptr_t; 

            // -----------------------------------------------------------------
            //    server - Public Constructors

            /** */
            server( connection_receiver_ptr_t p_receiver, 
                    handler_creator_ptr_t p_handler_creator )
                : m_receiver( p_receiver ),
                m_handlers ( connections_handlers_ptr_t( new connections_handlers( p_handler_creator ) ) ) {}

            /** Destructor */
            ~server ( ) {}

            // -----------------------------------------------------------------
            //    server - Public Accessors


            // -----------------------------------------------------------------
            //    server - Public Helpers


            // -----------------------------------------------------------------
            //    server - Public Processors

            void start( ) {

                while( true ) {

                    connection_event_ptr_t l_event = ( *m_receiver )( ) ;

                    if ( !l_event ) { break; }

                    m_handlers->handle( l_event ); 
                }
            }


            // -----------------------------------------------------------------
            //    server - Public Operators


            // -----------------------------------------------------------------
            //    server - Public Attributes


        private:

            // -----------------------------------------------------------------
            //    server - Private Internal Types

            typedef typename async::handlers<
                logger_t, 
                connection_event_t, 
                handler_t,
                handler_creator_t> connections_handlers;

            typedef typename connections_handlers::ptr_t connections_handlers_ptr_t;


            // -----------------------------------------------------------------
            //    server - Private Constructors


            // -----------------------------------------------------------------
            //    server - Private Accessors


            // -----------------------------------------------------------------
            //    server - Private Helpers


            // -----------------------------------------------------------------
            //    server - Private Processors


            // -----------------------------------------------------------------
            //    server - Private Operators


            // -----------------------------------------------------------------
            //    server - Private Attributes

            connection_receiver_ptr_t m_receiver;
            connections_handlers_ptr_t m_handlers;
        };

    }
}

// =============================================================================
//                     I M P L E M E N T A T I O N
// =============================================================================

using namespace tenacitas::distributed;


#endif
